#include <opencv2/opencv.hpp>

cv::Scalar bg_color = cv::Scalar(255, 255, 255, 255);

static int border_clip_reflect(int x, int size, int delta = 1);

// fedcba|abcdefgh|hgfedcb
int border_clip_reflect(int x, int size, int delta)
{
    if (x < 0)
    {
        return border_clip_reflect(-x - delta, size);
    }
    if (x > size - delta)
    {
        //return size-(x-size) - 1 => size - x + size - 1 => 2*size - x - 1
        return border_clip_reflect(2 * size - x - delta, size);
    }
    return x;
}

struct Pad
{
public:
    Pad(int _top, int _bottom, int _left, int _right):
        top(_top), bottom(_bottom), left(_left), right(_right)
    {}

public:
    int top;
    int bottom;
    int left;
    int right;
};

void update(cv::Mat& image, float& vy, float& y, float& vx, float& x)
{
    const int radius = 10;

    const int w = image.cols;
    const int h = image.rows;

    image = cv::Scalar(255, 255, 255, 255);

    float g = 9.8;
    vy = vy + g;
    y = y + vy;
    x = x + vx;
    // y 方向改变速度方向，并受阻尼影响变小
    if (y >= h - radius)
    {
        vy = vy * (-0.95);
        y = h - radius - 1;

        vx = vx * 0.98;
    }

    if (x >= w - radius)
    {
        vx = -vx;
        x = w - radius - 1;
    }
    else if (x <= radius)
    {
        vx = -vx;
        x = radius;
    }

    if (x >= 0)
    {
        cv::Point pt(x, y);

        cv::Scalar ball_color(0, 0, 0);
        const int thickness = -1;
        cv::circle(image, pt, radius, ball_color, thickness);
    }
}

int main()
{
    const int w = 640;
    const int h = 480;
    cv::Size size(w, h);
    cv::Mat image(size, CV_8UC3);

    int idx = 0;
    float vy = 20;
    float y = h / 4.0;
    float vx = 10;
    float x = w / 2.0;
    while (true)
    {
        update(image, vy, y, vx, x);
        idx++;

        cv::imshow("image", image);
        cv::waitKey(200);
    }

    return 0;
}